home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / ISSUE05 / EDSSPELL / EDSSPELL.ZIP / EDSSPELL.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-11-30  |  12.1 KB  |  391 lines

  1. unit EDSSpell;
  2.   {-Component Wrapper for Spell Dialog}
  3.  
  4. (*Revision History*)
  5. (* 11/15/95 - Added call so that all words can be added on         *)
  6. (*            unregistered version.                                *)
  7. (* 11/28/95 - Added apostrophe to valid characters (oops)          *)
  8. (* 11/30/95 - Added define for supporting the TDBMemos directly    *)
  9.  
  10. {.$DEFINE SupportDBMemos}  {-enable to support DBMemos}
  11.    {-enabling this will require your application to use the BDE}
  12. interface
  13. uses
  14.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  15.   Forms, Dialogs, StdCtrls, Buttons, Menus, ExtCtrls,
  16.   WSpell, SpellInt
  17. {$IFDEF SupportDBMemos}
  18.   ,DBCtrls;
  19. {$ELSE}
  20.   ;
  21. {$ENDIF}
  22.  
  23. type
  24.   {Dialog Component Wrapper}
  25.   TSpellDlg = class (TComponent)
  26.   private
  27.     FPath:           TFileName;
  28.     FDictionary:     TFileName;
  29.     FDicType:        Languages;
  30.     FSpellWin:       TSpellWin;
  31.     FSuggestions:    Byte;
  32.     FIcons:          AccentSet;
  33.     FAutoSuggest:    Boolean;
  34.     procedure   SetDicType (NewType: Languages);
  35.       {-sets the new dictionary type}
  36.     procedure   SetSuggestions (Num: Byte);
  37.       {-sets the number of suggestions}
  38.     procedure   SetIconSet (IconSet: AccentSet);
  39.       {-sets the icons to be visible}
  40.   public
  41.     constructor Create (AOwner: TComponent); override;
  42.       {-initializes object}
  43.     destructor  Destroy;  override;
  44.       {-destroys object}
  45.     procedure   Open;
  46.       {-opens the dictionary and displays dialog}
  47.     procedure   Close;
  48.       {-closes the dictionary and removes the dialog}
  49.     function    CheckWord (AWord: String): String;
  50.       {-checks the word}
  51.     procedure   CheckMemo (AMemo: TMemo);
  52.       {-checks the memo}
  53. {$IFDEF SupportDBMemos}
  54.     procedure   CheckDBMemo (ADBMemo: TDBMemo);
  55.       {-checks a database memo}
  56. {$ENDIF}
  57.  
  58.     {---- Internal Routines (No Dialog) ----}
  59.     function    OpenDictionary: Boolean;
  60.       {-opens the dictionary}
  61.     procedure   CloseDictionary;
  62.       {-closes the dictionary}
  63.     function    InDictionary (AWord: String): Boolean;
  64.       {-checks to see if the word is in the dictionary (no dialog)}
  65.     function    SuggestWords (AWord: String; NumToList: Byte): TStringList;
  66.       {-suggests words}
  67.   published
  68.     property AccentIcons:    AccentSet read FIcons write SetIconSet;
  69.     property DictionaryPath: TFileName read FPath write FPath;
  70.     property DictionaryName: TFileName read FDictionary write FDictionary;
  71.     property DictionaryType: Languages read FDicType write SetDicType;
  72.     property Suggestions:    Byte read FSuggestions write SetSuggestions;
  73.     property AutoSuggest:    Boolean read FAutoSuggest write FAutoSuggest;
  74.   end;  { TSpellDlg }
  75.  
  76. procedure Register;
  77.  
  78. implementation
  79.  
  80. {---- TSpellDlg.Wrapper ----}
  81. constructor TSpellDlg.Create (AOwner: TComponent);
  82. begin
  83.   inherited Create (AOwner);
  84.   FSpellWin   := TSpellWin.Create (Self);
  85.   FDictionary := '';
  86.   FPath       := 'ApplicationPath';
  87.   Suggestions := 5;
  88. end; { TSpellDlg.Create }
  89.  
  90. destructor TSpellDlg.Destroy;
  91. begin
  92.   FSpellWin.Destroy;
  93.   inherited Destroy;
  94. end;  { TSpellDlg.Destroy }
  95.  
  96. procedure TSpellDlg.SetDicType (NewType: Languages);
  97.   {-sets the new dictionary type}
  98. begin
  99.   FDicType := NewType;
  100.   with FSpellWin do
  101.   begin
  102.     case FDicType of
  103.       lgSpanish: Include (FIcons, acSpanish);
  104.     end;  { case }
  105.   end;  { case }
  106. end;  { TSpellDlg.SetDicType }
  107.  
  108. procedure TSpellDlg.SetSuggestions (Num: Byte);
  109. begin
  110.   if Num>10 then
  111.   begin
  112.     MessageDlg ('Maximum limit suggestions is 10.',
  113.                 mtInformation, [mbOk], 0);
  114.     FSuggestions := 10;
  115.   end {:} else
  116.   if Num<1 then
  117.   begin
  118.     MessageDlg ('Invlid number of suggestions.',
  119.                 mtInformation, [mbOk], 0);
  120.     FSuggestions := 1;
  121.   end {:} else
  122.     FSuggestions := Num;
  123.   FSpellWin.NumToSuggest := FSuggestions;
  124. end;  { TSpellDlg.SetSuggestions }
  125.  
  126. procedure TSpellDlg.SetIconSet (IconSet: AccentSet);
  127. begin
  128.   FIcons := IconSet;
  129.   with FSpellWin do
  130.   begin
  131.     lstSuggest.Top    := 48;
  132.     lstSuggest.Height := 161;
  133.     pnlIcons.Visible  := FALSE;
  134.     if acSpanish in FIcons then
  135.     begin
  136.       pnlIcons.Visible  := TRUE;
  137.       lstSuggest.Top    := lstSuggest.Top + pnlIcons.Height;
  138.       lstSuggest.Height := lstSuggest.Height - pnlIcons.Height;
  139.     end;  { if... }
  140.   end;  { with }
  141. end;  { TSpellDlg.SetIconSet }
  142.  
  143. procedure TSpellDlg.Open;
  144.   {-opens the dictionary and prepares dialog}
  145. begin
  146.   if not OpenDictionary then
  147.   begin
  148.     MessageDlg ('Error opening dictionary '+ FPath + FDictionary,
  149.                 mtError, [mbOk], 0);
  150.     Close;
  151.   end;  { if... }
  152. end;  { TSpellDlg.Open }
  153.  
  154. procedure TSpellDlg.Close;
  155.   {-closes the dictionary and removes the dialog}
  156. begin
  157.   FSpellWin.Close;
  158.   CloseDictionary;
  159. end;  { TSpellDlg.Close }
  160.  
  161. function TSpellDlg.CheckWord (AWord: String): String;
  162.   {-checks the word}
  163. var
  164.   Perform: byte;
  165. begin
  166.   if not FSpellWin.Visible then
  167.      Open ; {-open current dictionary}
  168.   {Set up window}
  169.   FSpellWin.Position            := poScreenCenter;
  170.   FSpellWin.lblNotFound.Caption := AWord;
  171.   FSpellWin.edtWord.Text        := AWord;
  172.   FSpellWin.btnSkip.Enabled     := FALSE;
  173.   FSpellWin.btnSkipAll.Enabled  := FALSE;
  174.   if InDictionary (AWord) then
  175.   begin
  176.     FSpellWin.lblFound.Caption := 'Word found:';
  177.   end {:} else
  178.   begin
  179.     FSpellWin.lblFound.Caption := 'Not found:';
  180.   end;  { else }
  181.   Perform := FSpellWin.ShowModal;
  182.   if PerForm = 20 then Result := FSpellWin.edtWord.Text
  183.                   else Result := '';
  184. end;  { TSpellDlg.CheckWord }
  185.  
  186. procedure TSpellDlg.CheckMemo (AMemo: TMemo);
  187.   {-checks the memo}
  188. var
  189.   WordSt:     string;   {current word}
  190.   OemSt:      string;   {OEM version of string}
  191.   CloseWin:   Boolean;  {TRUE if close window at end}
  192.   Buffer:     PBigBuffer; {memo buffer}
  193.   p:          pChar;    {pointer to current position in buffer}
  194.   Size:       Longint;  {size of buffer}
  195.   CurPos:     Longint;  {current position in buffer}
  196.   BeginPos:   Longint;  {beginning position of current word}
  197.   EndPos:     Longint;  {ending position of current word}
  198.   sSelStart:  Longint;  {saves the current attributes of Memo}
  199.   sSelLength: Longint;  { '' }
  200.   sHideSel:   Boolean;  { '' }
  201.   NoErrors:   Boolean;  {TRUE if all words are spelled correctly}
  202.   WinResult:  Byte;     {Result from ShowModal call}
  203.   SkipList:   TStringList;  {List of skipped words}
  204.   WordAdded:  Boolean;  {TRUE if a word was added}
  205.  
  206.   function GetNextWord: string;
  207.     {-returns the next word in the buffer}
  208.   const
  209.     ValidChars: Set Of Char =
  210.       [#39{'}, 'a'..'z', 'A'..'Z', #130{Θ},
  211.        #160{ß}..#165{╤}];
  212.   var
  213.     S: string;  {string being constructed}
  214.   begin
  215.     BeginPos := CurPos;
  216.     EndPos   := CurPos;
  217.     S        := '';
  218.     {find the first letter of the next word}
  219.     while (not (Char (p^) in ValidChars)) and
  220.           (CurPos<Size) do
  221.     begin
  222.       Inc (CurPos, 1);
  223.       p := @Buffer^[CurPos];
  224.     end; {  while }
  225.     if CurPos<Size then
  226.     begin
  227.       BeginPos := CurPos;
  228.       {goto the end of the word}
  229.       while ((Char (p^) in ValidChars) and
  230.              (CurPos<Size)) do
  231.       begin
  232.         S := ConCat (S, Char (p^));
  233.         Inc (CurPos, 1);
  234.         p := @Buffer^[CurPos];
  235.         EndPos := CurPos;
  236.       end;  { while }
  237.       Result := S;
  238.     end {:} else
  239.       Result := '';
  240.   end;  { GetNextWord }
  241.  
  242.   procedure UpdateBuffer;
  243.   begin
  244.     Size := AMemo.GetTextLen + 1;
  245.     AMemo.GetTextBuf (pChar(Buffer), Size);
  246.     AnsiToOemBuff (pChar (Buffer), pChar (Buffer), Size);
  247.   end;  { UpdateBuffer }
  248.  
  249. begin
  250.   sSelStart           := AMemo.SelStart;
  251.   sSelLength          := AMemo.SelLength;
  252.   sHideSel            := AMemo.HideSelection;
  253.   AMemo.HideSelection := FALSE;
  254.   WordAdded           := FALSE;
  255.   try
  256.     SkipList := TStringList.Create;
  257.     {FSpellWin.FormStyle := fsStayOnTop;}
  258.     CloseWin            := FALSE;
  259.     New (Buffer);
  260.     UpdateBuffer;
  261.     p      := @Buffer^[1];
  262.     CurPos := 1;
  263.     if not FSpellWin.Visible then
  264.     begin
  265.        Open ; {-open current dictionary}
  266.        CloseWin := TRUE;
  267.     end; {  if... }
  268.     {Set up window}
  269.     FSpellWin.Position            := poScreenCenter;
  270.     FSpellWin.btnSkip.Enabled     := TRUE;
  271.     FSpellWin.btnSkipAll.Enabled  := TRUE;
  272.     with AMemo do
  273.     begin
  274.       {calculate the upper most bounds for the memo}
  275.       {assume entire document for now}
  276.       NoErrors := TRUE;
  277.       repeat
  278.         WordSt := GetNextWord;
  279.         if not InDictionary (WordSt) then
  280.         begin
  281.           if SkipList.IndexOf (UpperCase (WordSt)) = (-1) then
  282.           begin
  283.             FSpellWin.lstSuggest.Clear;
  284.             NoErrors        := FALSE;
  285.             AMemo.SelStart  := BeginPos - 1;
  286.             AMemo.SelLength := EndPos - BeginPos;
  287.             AMemo.Update;
  288.             FSpellWin.lblFound.Caption    := 'Not found:';
  289.             FSpellWin.lblNotFound.Caption := WordSt;
  290.             FSpellWin.edtWord.Text        := WordSt;
  291.             if FAutoSuggest then
  292.               FSpellWin.btnSuggestClick (nil);
  293.             WinResult := FSpellWin.ShowModal;
  294.             case WinResult of
  295.               20: begin
  296.                 CurPos  := CurPos - (EndPos - BeginPos);
  297.                 AMemo.SelText := FSpellWin.edtWord.Text;
  298.                 CurPos  := CurPos + Length (FSpellWin.edtWord.Text);
  299.                 UpdateBuffer;
  300.                 p := @Buffer^[CurPos];
  301.               end;  { Replace }
  302.               21: begin
  303.                     {Add to dictionary}
  304.                     WordAdded := TRUE;
  305.                   end;  { 21 }
  306.               22: {SkipOnce};
  307.               23: begin
  308.                 {add word to skiplist}
  309.                 WordSt := UpperCase (WordSt);
  310.                 SkipList.Add (WordSt);
  311.               end;  { SkipAll }
  312.               mrCancel: break;
  313.             end;  { case }
  314.           end;  { if... }
  315.         end;  { if... }
  316.       until WordSt='';
  317.     end;  { with }
  318.     if CloseWin then FSpellWin.Close;
  319.     if WordAdded then dllCloseDictionary;
  320.   finally
  321.     SkipList.Free;
  322.     Dispose (Buffer);
  323.   end;  { try }
  324.   if NoErrors then
  325.     MessageDlg ('No errors found. Spell checking complete...', mtInformation,
  326.                 [mbOk], 0)
  327.   else
  328.   if WinResult=mrCancel then
  329.     MessageDlg ('Spell checking aborted...', mtInformation,
  330.                 [mbOk], 0)
  331.   else
  332.     MessageDlg ('Spell checking complete...', mtInformation,
  333.                 [mbOk], 0);
  334.   AMemo.SelStart      := sSelStart;
  335.   AMemo.SelLength     := sSelLength;
  336.   AMemo.HideSelection := sHideSel;
  337. end;  { TSpellDlg.CheckMemo }
  338.  
  339. {$IFDEF SupportDBMemos}
  340. procedure TSpellDlg.CheckDBMemo (ADBMemo: TDBMemo);
  341.   {-checks a database memo}
  342. begin
  343.   CheckMemo (TMemo (ADBMemo));
  344. end;  { TSpellDlg.CheckDBMemo }
  345. {$ENDIF}
  346.  
  347. {---- Internal Routines (No Dialog) ----}
  348.  
  349. function  TSpellDlg.OpenDictionary: Boolean;
  350.   {-opens the dictionary; returns TRUE if successful}
  351. begin
  352.   if DictionaryName='' then
  353.     DictionaryName := UpperCase (Dictionaries[DictionaryType] + DictExt);
  354.   DictionaryPath := UpperCase (DictionaryPath);
  355.   if DictionaryPath = 'APPLICATIONPATH' then
  356.     DictionaryPath := ExtractFilePath (Application.ExeName)
  357.   else
  358.   if Length (DictionaryPath)>0 then
  359.     if DictionaryPath[Length(DictionaryPath)]<>'\' then
  360.       DictionaryPath := DictionaryPath + '\';
  361.   Result := dllOpenDictionary (DictionaryPath + DictionaryName);
  362.   if not Result then
  363.     {try again for DLL load}
  364.     Result := dllOpenDictionary (DictionaryPath + DictionaryName);
  365. end;  { TSpellDlg.OpenDictionary }
  366.  
  367. procedure TSpellDlg.CloseDictionary;
  368.   {-closes the dictionary}
  369. begin
  370.   dllCloseDictionary;
  371. end;  { TSpellDlg.CloseDictionary }
  372.  
  373. function TSpellDlg.InDictionary (AWord: String): Boolean;
  374.   {-checks to see if the word is in the dictionary (no dialog)}
  375. begin
  376.   Result := dllInDictionary (AWord);
  377. end;  { TSpellDlg.InDictionary }
  378.  
  379. function TSpellDlg.SuggestWords (AWord: String; NumToList: Byte): TStringList;
  380.   {-suggests words}
  381. begin
  382.   Result := dllSuggestWords (AWord, NumToList);
  383. end;  { TSpellDlg.SuggestWords }
  384.  
  385. procedure Register;
  386. begin
  387.   RegisterComponents('Dialogs', [TSpellDlg]);
  388. end;  { Register }
  389.  
  390. end.  { EDSSpell }
  391.